package com.xlh.service.courseTest.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.xlh.dao.courseTest.ExperimentVideoStatisticsMapperExt;
import com.xlh.dto.courseTest.experiment.ExperimentChapterStatisticsTimeDTO;
import com.xlh.dto.courseTest.experiment.UserExperimentTimeInfoDTO;
import com.xlh.dto.user.UserInfoDTO;
import com.xlh.pojo.course.ChapterBasic;
import com.xlh.service.course.ChapterService;
import com.xlh.service.courseTest.ExperimentVideoStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @author sy
 */
@Service
public class ExperimentVideoStatisticsServiceImpl implements ExperimentVideoStatisticsService {

    /**
     * 视频统计mapper
     */
    @Autowired
    private ExperimentVideoStatisticsMapperExt videoStatisticsMapper;

    /**
     * 章节信息service
     */
    @Autowired
    private ChapterService chapterService;


    @Override
    public ExperimentChapterStatisticsTimeDTO loadExperimentTime(Long experimentChapterId, List<UserInfoDTO> userInfoDTOS) {

        ExperimentChapterStatisticsTimeDTO timeDTO = new ExperimentChapterStatisticsTimeDTO();
        ChapterBasic chapterInfo = chapterService.getChapterInfo(experimentChapterId);
        timeDTO.setName(chapterInfo.getName());

        if(CollectionUtil.isEmpty(userInfoDTOS)){
            List<UserExperimentTimeInfoDTO> attendData = Lists.newArrayList();
            timeDTO.setAttendData(attendData);
            return timeDTO;
        }

        UserExperimentTimeInfoDTO searchCondition = new UserExperimentTimeInfoDTO();
        searchCondition.setChapterId(experimentChapterId);

        // 1. 获取实验总时长
        List<UserExperimentTimeInfoDTO> leanTimeCount = videoStatisticsMapper.getLearnTimeCount(Lists.newArrayList(experimentChapterId), userInfoDTOS);
        // 2. 获取视频总时长
        List<UserExperimentTimeInfoDTO> videoTimeCount = videoStatisticsMapper.getVideoTimeCount(searchCondition, userInfoDTOS);
        // 3. 获取参与人员信息
        List<UserExperimentTimeInfoDTO> attendData = mergeUserInfo(leanTimeCount, videoTimeCount);
        // 4. 获取未参与人员信息
        List<UserExperimentTimeInfoDTO> notAttendData = getNotAttendData(userInfoDTOS, attendData);
        // 5. 封装返回对象
        attendData.addAll(notAttendData);
        attendData.forEach(timeInfoDTO -> timeInfoDTO.setTimeHourse());
        timeDTO.setName(chapterInfo.getName()).setAttendData(attendData);

        return timeDTO;
    }

    @Override
    public List<UserExperimentTimeInfoDTO> findLearnAndVideoTime(Long courseId, Long classId, List<Long> userIds, List<Long> taskIds) {

        // 转换为查询类型
        List<UserInfoDTO> userInfoDTOS = userIds.stream().map(UserInfoDTO::new).collect(Collectors.toList());
        // 设置查询条件
        UserExperimentTimeInfoDTO searchCondition = new UserExperimentTimeInfoDTO();
        searchCondition.setCourseId(courseId).setClassId(classId);
        // 1. 获取实验总时长
        List<UserExperimentTimeInfoDTO> leanTimeCount = videoStatisticsMapper.getLearnTimeCount(taskIds, userInfoDTOS);
        // 2. 获取视频总时长
        List<UserExperimentTimeInfoDTO> videoTimeCount = videoStatisticsMapper.getVideoTimeCountByTaskIds(searchCondition, userInfoDTOS,taskIds);
        // 3. 获取参与人员信息
        List<UserExperimentTimeInfoDTO> attendData = mergeUserInfo(leanTimeCount, videoTimeCount);
        Map<Long, List<UserExperimentTimeInfoDTO>> userMap = attendData.stream().collect(Collectors.groupingBy(UserExperimentTimeInfoDTO::getUserId));
        List<UserExperimentTimeInfoDTO> allUser = Lists.newArrayList();

        for (UserInfoDTO userInfoDTO : userInfoDTOS) {
            Long userId = userInfoDTO.getId();
            List<UserExperimentTimeInfoDTO> userExperimentTimeInfoDTOS = userMap.get(userId);
            if(Objects.isNull(userExperimentTimeInfoDTOS)){
                UserExperimentTimeInfoDTO notAttendUser = new UserExperimentTimeInfoDTO();
                notAttendUser.setClassId(classId);
                notAttendUser.setCourseId(courseId);
                notAttendUser.setUserId(userId);
                allUser.add(notAttendUser);
            }else{
                List<UserExperimentTimeInfoDTO> collect = userExperimentTimeInfoDTOS.stream().map(dto -> dto.setClassId(classId).setCourseId(courseId)).collect(Collectors.toList());
                allUser.addAll(collect);
            }
        }
        return allUser;
    }

    /**
     * 获取未参加学生信息
     * @param userInfoDTOS
     * @param attendData
     * @return
     */
    private List<UserExperimentTimeInfoDTO> getNotAttendData(List<UserInfoDTO> userInfoDTOS, List<UserExperimentTimeInfoDTO> attendData) {

        CopyOnWriteArrayList<UserInfoDTO> copyWriteAllUsers = Lists.newCopyOnWriteArrayList(userInfoDTOS);
        for (UserInfoDTO copyWriteAllUser : copyWriteAllUsers) {
            Long userId = copyWriteAllUser.getId();
            for (UserExperimentTimeInfoDTO attendDatum : attendData) {
                Long attendUserId = attendDatum.getUserId();
                if(userId.equals(attendUserId)){
                    copyWriteAllUsers.remove(copyWriteAllUser);
                    break;
                }
            }
        }
        // 转换数据  UserExperimentTimeInfoDTO
        List<UserExperimentTimeInfoDTO> notAttendData = copyWriteAllUsers.stream().map(userInfo -> {
            UserExperimentTimeInfoDTO timeInfo = new UserExperimentTimeInfoDTO();
            timeInfo.setUserId(userInfo.getId());
            timeInfo.setUserName(userInfo.getName());
            timeInfo.setLearnTime("0");
            timeInfo.setVideoTime("0");
            return timeInfo;
        }).collect(Collectors.toList());

        return notAttendData;
    }

    /**
     * 合并视频时长和学习时长实体类
     * @param leanTimeCount
     * @param videoTimeCount
     * @return
     */
    private List<UserExperimentTimeInfoDTO> mergeUserInfo(List<UserExperimentTimeInfoDTO> leanTimeCount, List<UserExperimentTimeInfoDTO> videoTimeCount) {

        if(leanTimeCount == null){
            leanTimeCount = Lists.newArrayList();
        }
        CopyOnWriteArrayList<UserExperimentTimeInfoDTO> videoTimeCountCopyOnWrite = Lists.newCopyOnWriteArrayList(videoTimeCount);
        for (UserExperimentTimeInfoDTO learnTime : leanTimeCount) {
            learnTime.initBaseColum();
            // BigDecimal LearnTimeHour = NumberUtil.div(learnTime.getLearnTime(), "3600", 2);
            learnTime.setLearnTime(learnTime.getLearnTime());
            Long learnUserId = learnTime.getUserId();
            for (UserExperimentTimeInfoDTO videoInfo : videoTimeCountCopyOnWrite) {
                Long videoUserId = videoInfo.getUserId();
                if(learnUserId.equals(videoUserId)){
                    videoInfo.initBaseColum();
                    // BigDecimal videoInfoHour = NumberUtil.div(videoInfo.getVideoTime(), "3600", 2);
                    learnTime.setVideoTime(videoInfo.getVideoTime());
                    videoTimeCountCopyOnWrite.remove(videoInfo);
                    break;
                }
            }
        }
        leanTimeCount.addAll(videoTimeCountCopyOnWrite);
        return leanTimeCount;
    }

}
